package com.example.client2;

import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import com.example.ipcdemo.pool.IBinderPool;
import com.example.ipcdemo.pool.INums;
import com.example.ipcdemo.pool.ISay;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

public class BinderPool {
    private static final String TAG = "BinderPool";
    public static final int BINDER_NUM = 1;
    public static final int BINDER_SAY = 2;






    //=======================================================
    //                  客户端应该调用的方法
    //=======================================================

    /**
     * Binder 服务，通过 binderCode 来查询当前的 Binder
     */
    public static class BinderPoolImpl extends IBinderPool.Stub{

        @Override
        public IBinder queryBinder(int binderCode) throws RemoteException {
            IBinder binder = null;
            switch (binderCode){
                case BINDER_NUM:
                    binder = new NumImpl();
                    break;
                case BINDER_SAY:
                    binder = new SayImpl();
                    break;
                default:break;

            }
            return binder;
        }
    }


    private static class SayImpl extends ISay.Stub{

        @Override
        public void speak(String msg) throws RemoteException {
            Log.d(TAG, "zsr speak: "+msg);
        }
    }
    private static class NumImpl extends INums.Stub{

        @Override
        public int add(int num1, int num2) throws RemoteException {
            Log.d(TAG, "zsr add: "+num1+" "+num2);
            return num1+num2;
        }
    }


    //=======================================================
    //                  客户端应该调用的方法
    //=======================================================

    private Context mContext;
    private static BinderPool mBinderPool;
    private RemoteService mRemoteService;
    private CountDownLatch mDownLatch;
    private IBinderPool mBinder;
    private BinderPool(Context context){
        mContext = context.getApplicationContext();
    }
    public static BinderPool getInstance(Context context){
        if (mBinderPool == null){
            synchronized (BinderPool.class){
                if (mBinderPool == null){
                    mBinderPool = new BinderPool(context);
                }
            }
        }
        return mBinderPool;
    }

    /**
     * 连接远程服务,考虑在多线程的问题
     */
    public synchronized void connectService(){

        mDownLatch = new CountDownLatch(1);
        /**
         * 绑定服务
         */
        Intent intent = new Intent();
        //绑定 服务
        intent.setClassName("com.example.ipcdemo","com.example.ipcdemo.service.PoolService");
        mRemoteService = new RemoteService();
        mContext.bindService(intent,mRemoteService, Service.BIND_AUTO_CREATE);

        try {
            mDownLatch.await(1000, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }




    class RemoteService implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mBinder = IBinderPool.Stub.asInterface(service);
            //添加 Binder 意外死亡的监听
            try {
                mBinder.asBinder().linkToDeath(mDeathRecipient,0);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            mDownLatch.countDown();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mBinder = null;
        }
    }

    /**
     * 通过 binderCode 查询 Binder
     * @param binderCode
     * @return
     */
    public synchronized IBinder queryBinder(int binderCode){
        IBinder binder = null;
        if (mBinder != null) {
            try {
                binder = mBinder.queryBinder(binderCode);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        return binder;
    }

    /**
     * 添加一个Binder意外死亡的监听
     */
    IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
        @Override
        public void binderDied() {
            mBinder.asBinder().unlinkToDeath(mDeathRecipient,0);
            mBinder = null;
            connectService();
        }
    };


    /**
     * 释放资源
     */
    public void onRelease(){
        if (mRemoteService != null) {
            mContext.unbindService(mRemoteService);
        }
    }

}
